<template>
  <Button class="mr-2" type="button" icon="pi pi-plus" label="新增"
          @click="() => {formState.dialogTitle = '新增图表', visibleCreate = true;}"/>
  <div class="grid grid-cols-4 gap-4 mt-2">
    <div class="gap-3 d-card " v-for="item in chartList" :class="item.chart === 'horizontal_bar' ? 'col-span-4' : ''">
      <div class="d-card-editor">
        <i class="pi pi-pen-to-square" style="font-size: 1rem" @click="() => openEditor(item)"></i>
      </div>
      <div v-if="item.chart === 'card'" class="bar-card cursor-pointer" :class="item.style"
           @click="() => instanceRef.visible(true, item.data, item.origin)">
        <div class="card-header">
          <i class="fas fa-exclamation-circle"></i> {{ item.title }}
        </div>
        <div class="card-body">
          <span class="count">{{ executeExpression(item.expression, item.data?.list) }}</span> {{ item.unit }}
        </div>
      </div>

      <div v-else-if="item.chart === 'horizontal_bar'" class="bar-card cursor-pointer " :class="item.style"
           @click="() => instanceRef.visible(true, item.data, item.origin)">
        <Chart type="bar" :data="item.data" :options="chartOptions" class="h-[30rem]"/>
      </div>
    </div>
  </div>
  <Instance ref="instanceRef"></Instance>

  <Dialog
      :header='formState.dialogTitle'
      modal
      style="width: 50%"
      v-model:visible="visibleCreate"
  >
    <v-ace-editor
        v-model:value="formState.content"
        lang="yaml"
        theme="chaos"
        style="height: 50vh"/>
    <div class="flex justify-between gap-2  mt-3">
      <Button type="button" label="删除" severity="danger" @click="dashboardDelete"></Button>
      <div>
        <Button type="button" label="取消" severity="secondary"
                @click="() => {visibleCreate = false}"></Button>
        <Button @click="dashboardCreate" label="提交" class="ml-2"></Button>
      </div>

    </div>
  </Dialog>
</template>

<script setup>
import {
  ApiInstanceList,
} from "@/api/cmdb.js";
import {
  ApiDashboardCreate,
  ApiDashboardList,
  ApiDashboardUpdate,
  ApiDashboardDelete,
  ApiDashboardSQLQuery
} from "@/api/dashboard.js"
import Chart from 'primevue/chart';
import yaml from 'js-yaml';
import {useToast} from "primevue/usetoast";
import {ref, reactive, computed, watch, onMounted} from "vue";
import {useRequest} from 'vue-request';
import Instance from "@/components/Instance.vue";
import {VAceEditor} from 'vue3-ace-editor';
import 'ace-builds/src-noconflict/mode-yaml.js';
import 'ace-builds/src-noconflict/mode-sh.js';
import 'ace-builds/src-noconflict/theme-chaos.js';

const toast = useToast();

const visibleCreate = ref(false)
const formState = reactive({
  content: '',
  dialogTitle: '新增图表'
})

const instanceRef = ref()


onMounted(() => {
  chartOptions.value = setChartOptions();
});

const chartOptions = ref();


const setChartOptions = () => {
  const documentStyle = getComputedStyle(document.documentElement);
  const textColor = documentStyle.getPropertyValue('--p-text-color');
  const textColorSecondary = documentStyle.getPropertyValue('--p-text-muted-color');
  const surfaceBorder = documentStyle.getPropertyValue('--p-content-border-color');

  return {
    maintainAspectRatio: false,
    aspectRatio: 0.8,
    plugins: {
      legend: {
        labels: {
          color: textColor
        }
      }
    },
    scales: {
      x: {
        ticks: {
          color: textColorSecondary,
          font: {
            weight: 500
          }
        },
        grid: {
          display: false,
          drawBorder: false
        }
      },
      y: {
        ticks: {
          color: textColorSecondary
        },
        grid: {
          color: surfaceBorder,
          drawBorder: false
        }
      }
    }
  };
}

function executeExpression(expression, data) {
  if (!data) {
    return 0
  }
  try {
    // 使用 new Function 来安全执行表达式
    return new Function('_data', 'return ' + expression)(data);
  } catch (error) {
    console.error('Invalid expression:', error);
    return null;
  }
}


const chartList = ref([])


const {
  loading: instanceLoading,
  run: instanceRun,
  refresh: dashboardRefresh
} = useRequest(ApiDashboardList, {
  onSuccess: async (e) => {
    chartList.value = []
    const data = e.data.list
    for (let i = 0; i < data.length; i++) {
      const jsonData = yaml.load(data[i].content);
      console.log(jsonData)
      if (jsonData.origin.source === 'cmdb') {
        const result = await ApiInstanceList(jsonData.origin)
        if (result.code === 0) {
          chartList.value.push({...jsonData, id: data[i].id, data: result.data, content: data[i].content})
        } else {
          chartList.value.push({...jsonData, id: data[i].id, content: data[i].content})
          toast.add({severity: 'error', summary: '错误', detail: result.msg, life: 3000});
        }
      } else if (jsonData.origin.source === 'sql') {
        ApiDashboardSQLQuery({sql: jsonData.origin.query.sql}).then(result => {
          if (result.code === 0) {
            if (result.data.list.length > 0) {
              let chartData = {}
              const queryData = result.data.list
              if (jsonData.chart === 'horizontal_bar') {
                const documentStyle = getComputedStyle(document.documentElement);
                chartData = {
                  labels: queryData.map(dict => dict['tool_name']),
                  datasets: [
                    {
                      label: jsonData.title,
                      backgroundColor: documentStyle.getPropertyValue('--p-cyan-500'),
                      borderColor: documentStyle.getPropertyValue('--p-cyan-500'),
                      data: queryData.map(dict => dict['count']),
                    }
                  ]
                };

                chartList.value.push({...jsonData, id: data[i].id, data: chartData, content: data[i].content})
              } else if (jsonData.chart === 'card') {
                chartList.value.push({...jsonData, id: data[i].id, data: result.data, content: data[i].content})
              }
            }

          } else {
            chartList.value.push({...jsonData, id: data[i].id, content: data[i].content})
            toast.add({severity: 'error', summary: '错误', detail: result.msg, life: 3000});
          }
        })
      }

      console.log('chartList', chartList)

    }
  }
})

const dashboardCreate = async () => {
  let result;
  if (formState.id) {
    console.log(formState)
    result = await ApiDashboardUpdate(formState.id, {content: formState.content})
  } else {
    result = await ApiDashboardCreate({content: formState.content})

  }
  if (result.code === 0) {
    toast.add({severity: 'success', summary: '成功', detail: result.msg, life: 3000});
    visibleCreate.value = false
    await dashboardRefresh()
  } else {
    toast.add({severity: 'error', summary: '错误', detail: result.msg, life: 3000});
  }
}

const openEditor = async (data) => {
  formState.dialogTitle = '编辑图表'
  visibleCreate.value = true
  formState.content = data.content
  formState.id = data.id
}

const dashboardDelete = async () => {
  const result = await ApiDashboardDelete(formState.id)
  if (result.code === 0) {
    toast.add({severity: 'success', summary: '成功', detail: result.msg, life: 3000});
    visibleCreate.value = false
    await dashboardRefresh()
  } else {
    toast.add({severity: 'error', summary: '错误', detail: result.msg, life: 3000});
  }
}

</script>

<style scoped>
.dashboard {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
  padding: 20px;
  font-family: 'Arial', sans-serif;
}

.bar-card {
  background: linear-gradient(135deg, #ffffff, #f3f4f7);
  border-radius: 15px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
  padding: 30px;
  text-align: center;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}


.card-header {
  font-size: 20px;
  margin-bottom: 15px;
  color: #444;
  font-weight: bold;
}

.card-body {
  font-size: 30px;
  font-weight: bold;
  color: #333;
}

.count {
  font-size: 48px;
  font-weight: bold;
  color: #007bff;
}

.card_background_1 {
  background-color: #eef7ff;
  background: linear-gradient(135deg, #e0f7ff, #cce0ff);
}

.healthy-card_background_2 {
  background-color: #e6f7e9;
  background: linear-gradient(135deg, #d1f7d9, #a8f0b8);
}

.fault-card_background_3 {
  background-color: #fdecec;
  background: linear-gradient(135deg, #fcd1d1, #f7baba);
}

.card i {
  font-size: 24px;
  margin-right: 10px;
  color: #007bff;
}

.d-card {
  position: relative;
}

.d-card-editor {
  position: absolute;
  right: 20px;
  top: 15px;
}
</style>
